<?php
//+---------------------------------------------------------------------------------------------------------------------
//| 人生是荒芜的旅行，冷暖自知，苦乐在心
//+---------------------------------------------------------------------------------------------------------------------
//| Author:Janmas <janmas@126.com>
//+---------------------------------------------------------------------------------------------------------------------
//| 
//+---------------------------------------------------------------------------------------------------------------------


namespace app\common\plugins\flow;


use app\admin\model\Menu;
use helper\file\File;
use app\admin\model\Config;
use app\common\plugins\Plugin;
use app\common\exception\PluginException;
use app\admin\model\Plugin as PluginModel;
use think\Exception;

/**
 * Class Install
 * @package app\common\plugins\flow
 * @property \app\admin\model\Plugin $model
 * @property Plugin $plugin
 */
class Install
{
	protected $plugin;

	protected $pluginPath = '';

	/**
	 * 插件名
	 * @var string
	 */
	protected $name = '';

	/**
	 * 插件标识
	 * @var string
	 */
	protected $flag = '';

	protected $model = null;

	public function __construct( Plugin $plugin )
	{
		$this->plugin = $plugin;
		$this->flag = $this->plugin->getFlag();
		$this->pluginPath = $this->plugin->getPluginPath() . $this->flag . DIRECTORY_SEPARATOR;
		$this->name = $this->plugin->getName();
		$this->model = new PluginModel();
	}

	public function make()
	{
		if($this->plugin->getInstalled()){
			$res = $this->model->where('flag',$this->flag)->update(['is_install'=>1]);
			if($res !== false) return true;
			return false;
		}

		$this->model->startTrans();
		try{
			$this->installInfo();
			$this->installConfig();
			$this->installMenu();
			$this->installStaticResource();
			$this->plugin->install();
            $this->model->commit();
			return true;
		}catch(PluginException $e){
            $this->model->rollback();
			throw $e;
		}catch(\Exception $e){
			throw new PluginException($e->getMessage());
		}

	}

	/**
	 * 加载插件信息
	 * @return bool
	 */
	protected function installInfo()
	{
		$insert = $this->plugin->getInfo();
		if ( !$insert ){
			throw new PluginException(sprintf('插件 %s 不存在基本信息（info.json文件）', $this->flag));
		}

        $isCreate = false;
		$model = PluginModel::where('flag',$this->flag)->findOrEmpty();
		if(!$model->isEmpty() && $model->is_install == 1){
			throw new PluginException('插件已安装');
		}elseif($model->isEmpty()){
            $isCreate = true;
        }

		$insert['is_install'] = 1;
		if($isCreate){
            $result = $this->model->create($insert);
        }else{
		    $result = $this->model->where('flag',$this->flag)->data($insert)->save();
        }

		if ($result){
			return true;
		}
		throw new PluginException('保存插件基础信息失败,稍后重试');
	}

	/**
	 * 加载配置信息
	 * @return bool
	 */
	protected function installConfig()
	{
		$insert = $this->plugin->getConfig();
		if ( empty($insert) ){
			return true;
		}
		$add = ['group'=>$this->flag,'status'=>1];

		array_walk($insert, function (&$value, $key, $add) {
			$value = array_merge($value, $add);
		}, $add);
        $model = $this->model;
		$configModel = new Config();
		if (
		    false !== $configModel->where('group',$this->flag)->delete() &&
            $configModel->failException(true)->insertAll($insert) &&
            false !== $model->failException(true)->where('flag',$this->flag)->data(['is_config'=>1])->update()
        ){
			return true;
		}

		throw new PluginException('保存插件配置信息失败，稍后重试');
	}

	/**
	 * 加载菜单
	 * @return bool
	 */
	private function installMenu()
	{
		$menus = $this->plugin->getMenus();
		$model = $this->model;
        if ( empty($menus) ){
			return true;
		}
		if (
		    $this->menu($menus) &&
            $model->failException(true)->where('flag',$this->flag)->data(['is_menu'=>1])->update() !== false
        ){
			return true;
		}
		throw new PluginException('保存插件菜单信息失败');
	}

	/**
	 * 加载静态资源
	 * @return bool
	 */
	protected function installStaticResource(){
		/**
		 * 静态资源
		 * css,js,img
		 */
		$publicDir = app()->getRootPath() . 'public' . DIRECTORY_SEPARATOR . 'plugins' .DIRECTORY_SEPARATOR .  $this->flag . DIRECTORY_SEPARATOR;
		File::copy($this->pluginPath.$this->plugin->getInfo()['icon']??'icon'.'.png', $publicDir.$this->plugin->getInfo('icon')['icon']??'icon'.'.png');
		File::move($this->pluginPath.'static', $publicDir.'static');
		File::touch($this->pluginPath.'install.lock');
		return true;
	}

	/**
	 * 循环菜单
	 * @param $menus
	 * @param null $parentId
	 * @return bool
	 */
	private function menu( $menus, $parentId = 0 )
	{
	    if(empty($menus)){
	        return true;
        }
	    $res = null;
	    foreach($menus as $menu){
	    	if(is_array($menu)){
			    $menu['pid'] = $parentId;
			    $menu['flag'] = $this->flag;
			    $model = new Menu();
			    $res = $model->create($menu);
			    if(!$res) return false;
			    if(isset($menu['children'])){
				     $this->menu($menu['children'],$res->id);
			    }
		    }
	    }
		return $res;

	}


}